package com.example.xgsweather.fragment;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.fragment.app.Fragment;

import com.example.xgsweather.R;
import com.example.xgsweather.activity.MainActivity;
import com.example.xgsweather.activity.ManageCitiesActivity;
import com.example.xgsweather.activity.WeatherFragmentActivity;
import com.example.xgsweather.db.City;
import com.example.xgsweather.db.County;
import com.example.xgsweather.db.FrequentlyUsedCity;
import com.example.xgsweather.db.Province;
import com.example.xgsweather.util.HandleResponseUtil;
import com.example.xgsweather.util.LogUtil;
import com.qweather.sdk.bean.base.Code;
import com.qweather.sdk.bean.base.Range;
import com.qweather.sdk.bean.geo.GeoBean;
import com.qweather.sdk.view.QWeather;

import org.litepal.LitePal;

import java.util.ArrayList;
import java.util.List;

/**
 * 用于遍历省市县数据
 */
public class ChooseAreaFragment extends Fragment {
    /**
     * 列表级别
     */
    public static final int LEVEL_PROVINCE = 0;
    public static final int LEVEL_CITY = 1;
    public static final int LEVEL_COUNTY = 2;
    /**
     * 进度对话框
     */
    private ProgressDialog progressDialog;
    private EditText searchEditText;
    private TextView titleText;
    private Button backButton;
    private ListView areaListView;
    private ListView searchResultList;
    private ArrayAdapter<String> areaAdapter;
    private ArrayAdapter<String> resultAdapter;
    private List<String> dataList = new ArrayList<>();
    private List<String> resultList = new ArrayList<>();
    /**
     * 搜索城市的结果的
     */
    private List<GeoBean.LocationBean> resultLocationBeans;
    /**
     * 省列表
     */
    private List<Province> provinceList;
    /**
     * 市列表
     */
    private List<City> cityList;
    /**
     * 县列表
     */
    private List<County> countyList;
    /**
     * 选中的省份
     */
    private Province selectedProvince;
    /**
     * 选中的城市
     */
    private City selectedCity;
    /**
     * 当前选中的级别
     */
    private int currentLevel;

    /**
     * 是否‘不需要’请求网络更新数据库的市县数据？
     */
    public static boolean noNeedToUpdate = true;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        LogUtil.d("ChooseAreaFragment onCreateView");
        View view = inflater.inflate(R.layout.choose_area, container, false);
        // 获取控件实例
        searchEditText = view.findViewById(R.id.search_area_edit);
        titleText = view.findViewById(R.id.title_text);
        backButton = view.findViewById(R.id.back_button);
        areaListView = view.findViewById(R.id.area_list_view);
        searchResultList = view.findViewById(R.id.search_result_list);
        // 初始化adapter
        areaAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, dataList);
        areaListView.setAdapter(areaAdapter);
        resultAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, resultList);
        searchResultList.setAdapter(resultAdapter);
        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        LogUtil.d("ChooseAreaFragment onActivityCreated");
        super.onActivityCreated(savedInstanceState);

        // 监听搜索框文字的改变
        searchEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence c, int i, int i1, int i2) {
                // LogUtil.d("字数1:" + c.length() + "," + i + "," + i1 + "," + i2);
                if (c.length() > 0) {
                    // LogUtil.w("字数2:" + c.length() + "," + i + "," + i1 + "," + i2);
                    areaListView.setVisibility(View.GONE);
                    doSearchArea();
                } else {
                    // LogUtil.e("字数3:" + c.length() + "," + i + "," + i1 + "," + i2);
                    areaListView.setVisibility(View.VISIBLE);
                    searchResultList.setVisibility(View.GONE);
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {
            }
        });
        // 搜索框失去焦点的监听
        searchEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!(searchEditText.getText().toString().trim().isEmpty())) {
                    areaListView.setVisibility(View.GONE);
                    if (!hasFocus) {
                        doSearchArea();
                    }
                } else if (searchEditText.getText().toString().trim().isEmpty()) {
                    areaListView.setVisibility(View.VISIBLE);
                    searchResultList.setVisibility(View.GONE);
                }
            }
        });
        // 按下键盘回车键搜索
        searchEditText.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
                    // 隐藏键盘
                    ((InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE))
                            .hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
                    searchEditText.clearFocus();
                    doSearchArea();
                    return true;
                }
                return false;
            }
        });

        // 给ListView和Button设置点击事件
        searchResultList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String weatherId = resultLocationBeans.get(position).getId();
                String countyName = resultLocationBeans.get(position).getName();
                    /*  因为第一次是选中了某个城市后是跳转到WeatherActivity的，而后面切换城市本来就是在WeatherActivity当中的，
                    因此并不需要跳转，只是去请求新选择城市的天气信息就可以了。所以要在这里进行一下判断。
                    */
                if (getActivity() instanceof MainActivity) {
                    if ((LitePal.where("weatherId = ? and cityName = ?", weatherId, countyName).find(FrequentlyUsedCity.class)).size() == 0) {
                        new FrequentlyUsedCity(weatherId, countyName).save();
                    }
                    Intent intent = new Intent(getActivity(), WeatherFragmentActivity.class);
                    intent.putExtra("weather_id", weatherId);
                    intent.putExtra("county_name", countyName);
                    intent.putExtra("position", 0);
                    startActivity(intent);
                    getActivity().finish();
                } else if (getActivity() instanceof ManageCitiesActivity) {
                    if ((LitePal.where("weatherId = ? and cityName = ?", weatherId, countyName).find(FrequentlyUsedCity.class)).size() == 0) {
                        new FrequentlyUsedCity(weatherId, countyName).save();
                        Intent intent = new Intent(getActivity(), WeatherFragmentActivity.class);
                        intent.putExtra("weather_id", weatherId);
                        intent.putExtra("county_name", countyName);
                        intent.putExtra("position", LitePal.findAll(FrequentlyUsedCity.class).size() - 1);
                        startActivity(intent);
                        getActivity().finish();
                    } else {
                        Toast.makeText(getActivity(), "该城市已经添加过了", Toast.LENGTH_SHORT).show();
                        ((ManageCitiesActivity) getActivity()).onBackPressed();
                    }
                } else if (getActivity() instanceof WeatherFragmentActivity) {
                    searchEditText.setText("");
                    WeatherFragmentActivity weatherActivity2 = (WeatherFragmentActivity) getActivity();
                    weatherActivity2.requestWeatherForQWeather(weatherId, countyName);
                }
            }
        });
        areaListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (currentLevel == LEVEL_PROVINCE) {
                    selectedProvince = provinceList.get(position);
                    queryCities();
                } else if (currentLevel == LEVEL_CITY) {
                    selectedCity = cityList.get(position);
                    queryCounties();
                } else if (currentLevel == LEVEL_COUNTY) {
                    String weatherId = countyList.get(position).getCountyCode();
                    String countyName = countyList.get(position).getCountyName();
                    /*  因为第一次是选中了某个城市后是跳转到WeatherActivity的，而后面切换城市本来就是在WeatherActivity当中的，
                    因此并不需要跳转，只是去请求新选择城市的天气信息就可以了。所以要在这里进行一下判断。
                    */
                    if (getActivity() instanceof MainActivity) {
                        if ((LitePal.where("weatherId = ? and cityName = ?", weatherId, countyName).find(FrequentlyUsedCity.class)).size() == 0) {
                            new FrequentlyUsedCity(weatherId, countyName).save();
                        }
                        Intent intent = new Intent(getActivity(), WeatherFragmentActivity.class);
                        intent.putExtra("weather_id", weatherId);
                        intent.putExtra("county_name", countyName);
                        intent.putExtra("position", 0);
                        startActivity(intent);
                        getActivity().finish();
                    } else if (getActivity() instanceof ManageCitiesActivity) {
                        if ((LitePal.where("weatherId = ? and cityName = ?", weatherId, countyName).find(FrequentlyUsedCity.class)).size() == 0) {
                            new FrequentlyUsedCity(weatherId, countyName).save();
                            Intent intent = new Intent(getActivity(), WeatherFragmentActivity.class);
                            intent.putExtra("weather_id", weatherId);
                            intent.putExtra("county_name", countyName);
                            intent.putExtra("position", LitePal.findAll(FrequentlyUsedCity.class).size() - 1);
                            startActivity(intent);
                            getActivity().finish();
                        } else {
                            Toast.makeText(getActivity(), "该城市已经添加过了", Toast.LENGTH_SHORT).show();
                            ((ManageCitiesActivity) getActivity()).onBackPressed();
                        }
                    } else if (getActivity() instanceof WeatherFragmentActivity) {
                        searchEditText.setText("");
                        WeatherFragmentActivity weatherActivity2 = (WeatherFragmentActivity) getActivity();
                        weatherActivity2.requestWeatherForQWeather(weatherId, countyName);
                    }
                }
            }
        });

        backButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (currentLevel == LEVEL_COUNTY) {
                    queryCities();
                } else if (currentLevel == LEVEL_CITY) {
                    queryProvinces();
                } else if (getActivity() instanceof ManageCitiesActivity) {
                    getActivity().onBackPressed();
                }
            }
        });
        queryProvinces();
    }

    /**
     * 查询全国所有的省，优先从数据库查询，如果没有查询到再去服务器上查询
     */
    private void queryProvinces() {
        titleText.setText("选择城市");
        if (getActivity() instanceof WeatherFragmentActivity) {
            titleText.setText("更改当前城市");
        }
        // 隐藏返回按钮，因为省级列表已经不能再返回了
        backButton.setVisibility(View.GONE);
        if (getActivity() instanceof ManageCitiesActivity) {
            backButton.setVisibility(View.VISIBLE);
        }
        // 调用LitePal的查询接口从数据库查询
        provinceList = LitePal.findAll(Province.class);
        if (provinceList.size() > 0) {
            dataList.clear();
            for (Province province : provinceList) {
                dataList.add(province.getProvinceName());
            }
            areaAdapter.notifyDataSetChanged();
            // 设置当前默认选定的省份
            areaListView.setSelection(0);
            currentLevel = LEVEL_PROVINCE;
        } else {
            // 从数据库没有查询到，再从 provinces.json资源文件加载到数据库，然后再查询
            HandleResponseUtil.handleProvinceResponse(getContext());
            queryProvinces();
        }
    }

    /**
     * 查询选中省内所有的市
     */
    private void queryCities() {
        titleText.setText(selectedProvince.getProvinceName());
        backButton.setVisibility(View.VISIBLE);
        cityList = LitePal.where("provinceid = ?", String.valueOf(selectedProvince.getId())).find(City.class);
        if (cityList.size() > 0 && noNeedToUpdate) {
            dataList.clear();
            for (City city : cityList) {
                dataList.add(city.getCityName());
            }
            areaAdapter.notifyDataSetChanged();
            areaListView.setSelection(0);
            currentLevel = LEVEL_CITY;
        } else {
            String provinceName = String.valueOf(selectedProvince.getProvinceName());
            queryFromServer(provinceName, "city");
        }
    }

    /**
     * 查询选中市内所有的县
     */
    private void queryCounties() {
        titleText.setText(selectedCity.getCityName());
        backButton.setVisibility(View.VISIBLE);
        countyList = LitePal.where("cityid = ?", String.valueOf(selectedCity.getId())).find(County.class);
        if (countyList.size() > 0 && noNeedToUpdate) {
            dataList.clear();
            for (County county : countyList) {
                dataList.add(county.getCountyName());
            }
            areaAdapter.notifyDataSetChanged();
            areaListView.setSelection(0);
            currentLevel = LEVEL_COUNTY;
        } else {
            String cityName = String.valueOf(selectedCity.getCityName());
            queryFromServer(cityName, "county");
        }
    }

    /**
     * 根据传入的地址和类型从服务器上查询省市县数据
     */
    private void queryFromServer(String locationID, String type) {
        noNeedToUpdate = true;
        showProgressDialog();
        Context context = getActivity().getApplicationContext();
        QWeather.getGeoCityLookup(context, locationID, Range.CN, 15, null, new QWeather.OnResultGeoListener() {
            @Override
            public void onError(Throwable e) {
                LogUtil.e("ChooseAreaFragment queryFromServer onError: " + e);
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        closeProgressDialog();
                    }
                });
            }

            @Override
            public void onSuccess(GeoBean geoBean) {
                if (Code.OK == geoBean.getCode()) {
                    List<GeoBean.LocationBean> locationBeanList = geoBean.getLocationBean();
                    boolean result = false;
                    if ("city".equals(type)) {
                        result = HandleResponseUtil.handleCityResponse(locationBeanList, selectedProvince.getId());
                    } else if ("county".equals(type)) {
                        result = HandleResponseUtil.handleCountyResponse(locationBeanList, selectedCity.getId());
                    }
                    if (result) {
                        // 解析数据成功并存到数据库之后再进行后面的操作
                        getActivity().runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                closeProgressDialog();
                                if ("city".equals(type)) {
                                    queryCities();
                                } else if ("county".equals(type)) {
                                    queryCounties();
                                }
                            }
                        });
                    }
                } else {
                    //在此查看返回数据失败的原因
                    Code code = geoBean.getCode();
                    LogUtil.e("queryFromServer failed code: " + code);
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            closeProgressDialog();
                        }
                    });
                }
            }
        });
    }

    private void doSearchArea() {
        Context context = getActivity().getApplicationContext();
        String loc = searchEditText.getText().toString().trim();
        if (loc.isEmpty()) return;
        QWeather.getGeoCityLookup(context, loc, Range.CN, 10, null, new QWeather.OnResultGeoListener() {
            @Override
            public void onError(Throwable e) {
                LogUtil.e("ChooseAreaFragment doSearchArea onError: " + e);
            }

            @Override
            public void onSuccess(GeoBean geoBean) {
                if (Code.OK == geoBean.getCode()) {
                    resultLocationBeans = geoBean.getLocationBean();
                    // 解析数据成功并存到数据库之后再进行后面的操作
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            resultList.clear();
                            for (int i = 0; i < resultLocationBeans.size(); i++) {
                                String cityName = resultLocationBeans.get(i).getName();
                                String cityAdm2 = resultLocationBeans.get(i).getAdm2();
                                String cityAdm1 = resultLocationBeans.get(i).getAdm1();
                                String cityCountry = resultLocationBeans.get(i).getCountry();
                                resultList.add(cityName + "，" + cityAdm2 + "，" + cityAdm1 + "，" + cityCountry);
                            }
                            resultAdapter.notifyDataSetChanged();
                            searchResultList.setSelection(0);
                            searchResultList.setVisibility(View.VISIBLE);
                            if (searchEditText.getText().toString().trim().isEmpty()) {
                                areaListView.setVisibility(View.VISIBLE);
                                searchResultList.setVisibility(View.GONE);
                            }
                        }
                    });
                } else {
                    //在此查看返回数据失败的原因
                    Code code = geoBean.getCode();
                    LogUtil.e("doSearchArea failed code: " + code);
                }
            }
        });
    }

    /**
     * 显示进度对话框
     */
    private void showProgressDialog() {
        if (progressDialog == null) {
            progressDialog = new ProgressDialog(getActivity());
            progressDialog.setMessage("正在加载...");
            progressDialog.setCanceledOnTouchOutside(false);
        }
        progressDialog.show();
    }

    /**
     * 关闭进度对话框
     */
    private void closeProgressDialog() {
        if (progressDialog != null) {
            progressDialog.dismiss();
        }
    }

}

